package cn.gdcp.servicebestpractice;

import android.os.AsyncTask;
import android.os.Environment;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class DownloadTask extends AsyncTask<String,Integer,Integer> {
    public  static final int TYPE_SUCCESS=0;
    public  static final int TYPE_FAILED=1;
    public  static final int TYPE_PAUSED=2;
    public  static final int TYPE_CANCLED=3;
    private DownloadListener listener;
    private boolean isCancled=false;
    private boolean isPaused=false;
    private int lastProgress;

    public DownloadTask(DownloadListener listener) {
       this.listener=listener;
    }

    protected Integer doInBackground(String... strings) {
        InputStream is=null;
        RandomAccessFile savedFile=null;
        File file=null;
        try{
            long downloadLength=0;
            String downloadUrl=strings[0];
            String fileName=downloadUrl.substring(downloadUrl.lastIndexOf("/"));
            String directory= Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath();
            file=new File(directory+fileName);
            if(file.exists()){
                downloadLength=file.length();
            }
            long contentLength=getContLength(downloadUrl);
            if (contentLength==0){
                return TYPE_FAILED;
            }else if (contentLength==downloadLength){
                return TYPE_SUCCESS;
            }
            OkHttpClient client=new OkHttpClient();
            Request request=new Request.Builder().addHeader("RANGE","byte="+downloadLength+"-")
                    .url(downloadUrl).build();
            Response response=client.newCall(request).execute();
            if (response!=null){
                is=response.body().byteStream();
                savedFile=new RandomAccessFile(file,"rw");
                savedFile.seek(downloadLength);
                byte[] b=new byte[1024];
                int total=0;
                int len;
                while ((len=is.read(b))!=-1){
                    if (isCancled){
                        return TYPE_CANCLED;
                    }else if (isPaused){
                        return TYPE_PAUSED;
                    }else {
                        total+=len;
                        savedFile.write(b,0,len);
                        int progress=(int)((total+downloadLength)*100/contentLength);
                        publishProgress(progress);
                    }
                }
                response.body().close();
                return TYPE_SUCCESS;
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try{
                     if (is!=null){is.close();}
                     if (savedFile!=null){
                         savedFile.close();
                     }
                     if (isCancled&&file!=null){
                         file.delete();
                     }
            }
                  catch (Exception e){
                    e.printStackTrace();
                     }
        }

           return TYPE_FAILED;
    }

    private long getContLength(String downloadUrl) throws IOException{

        OkHttpClient client=new OkHttpClient();
        Request request=new Request.Builder().url(downloadUrl).build();
        Response response=client.newCall(request).execute();
        long contentLength=response.body().contentLength();
        response.close();
        if (response!=null&&response.isSuccessful()){
        return contentLength;}
        return 0;
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
     int progress=values[0];
     if (progress>lastProgress){
         listener.onProgress(progress);
         lastProgress=progress;
     }
    }

    protected void onPostExecute(Integer integer) {
      switch (integer){
          case TYPE_SUCCESS:
              listener.onSuccess();
              break;
          case TYPE_FAILED:
              listener.onFailed();
              break;
          case TYPE_CANCLED:
              listener.onCanceld();
              break;
          case TYPE_PAUSED:
              listener.onFailed();
              break;
              default:
                  break;
                  }
                  }
                  public void  pauseDownload(){
                      isPaused=true;
                  }
                  public void cancelDownload(){
                       isCancled=true;
                  }
}
